home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
glass
/
glass.lha
/
GLASS
/
tmc
/
calu.ct
< prev
next >
Wrap
Text File
|
1990-11-06
|
38KB
|
1,888 lines
/*
Copyright (C) 1990 C van Reewijk, email: dutentb.uucp!reeuwijk
This file is part of GLASS.
GLASS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GLASS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GLASS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
.. file: calu.ct
.. tm C support. Variant: array lists, union constructors.
..
.. The following variables must be set in tm:
.. basename: the name of the module. used to generate init_.. and stat_..
.. wantdefs: the names of the wanted definitions.
.. OR
.. alldefs: All code.
..
.. The following C pre-processor variables may be defined:
.. STAT If you want code for statistics.
.. Statistics are written to 'FILE *statstream'.
.. FATAL(msg) If you want to supply a fatal error handler to print 'msg'.
.. A default is provided.
.. FIRSTROOM Initial room in lists. A default is provided.
.. DUMMYCODE If not defined to 0, dummy code is generated that gives
.. the same impression as the real code to lint, but is much
.. smaller. If not defined, it is defined locally to be 1
.. if 'lint' is defined, else it is defined to be 0.
..
.. Possible declaration or #define'ing of statstream must be done
.. outside this module.
.set teststdc "#if defined( __STDC__ ) && __STDC__>0"
.if ${index stat_$(basename) $(need_misc)}
.set statcode 1
.else
.set statcode 0
.endif
/* ---- start of ${tplfilename} ---- */
/* Routines for '$(basename)'.
template file: ${tplfilename}
datastructure file: ${dsfilename}
tm version: $(tmvers) ($(tmdate))
*/
$(teststdc)
#else
#define const
#endif
/* The defines below are necessary to stop complaints on various machines
* about incompatible types to realloc() and free(). On hpux v7.0 a void *
* are used, but not interpreted as a neutral pointer type. AAAARGGHHH.
*/
$(teststdc)
#define TMREALLOC realloc
#define TMFREE free
#else
#ifdef hp9000s300
/* Actually, this is not accurate enough, but I don't know how to
* solve this.
*/
#define TMREALLOC(p,n) realloc((void *)(p),n)
#define TMFREE(p) free((void *)(p))
#else
#define TMREALLOC(p,n) realloc((char *)(p),n)
#define TMFREE(p) free((char *)(p))
#endif
#endif
/* If DUMMYCODE is 1, fake code is generated to give lint the right
* impression of the real code and not choke it with
* that real code.
*/
#ifndef DUMMYCODE
#define DUMMYCODE 0
#endif
#if DUMMYCODE==0
.if $(statcode)
#ifdef STAT
.foreach t $(need_stat_list)
static long newcnt_$t_list = 0;
static long frecnt_$t_list = 0;
static long hitcnt_$t_list = 0;
.endforeach
.foreach t $(need_stat)
.if ${strlen ${telmlist $t}}
static long newcnt_$t = 0;
static long frecnt_$t = 0;
static long hitcnt_$t = 0;
.else
.foreach c ${conslist $t}
static long newcnt_$c = 0;
static long frecnt_$c = 0;
static long hitcnt_$c = 0;
.endforeach
.endif
.endforeach
#endif
.endif
/* Caching variables.
*
* For each type or type list array of CACHESZ elements is maintained that
* is filled by the fre_<type>() routines. If possible new_<type>() or
* new_<cons> uses these elements.
*
* Although type elements can be shared by all constructors of a type, the
* cache hit counts are maintained separately.
*
* All cacheix_<type> variables maintain the index of the first
* free element in the array.
*/
#ifndef CACHESZ
#define CACHESZ 5
#endif
#ifdef USECACHE
#undef USECACHE
#endif
#if CACHESZ==0
#else
#define USECACHE
#endif
#ifdef USECACHE
.foreach t ${uniq $(need_new_list) $(need_fre_list)}
static short int cacheix_$t_list = 0;
static $t_list cache_$t_list[CACHESZ];
.endforeach
.foreach t ${uniq $(need_new) $(need_fre)}
static short int cacheix_$t = 0;
static $t cache_$t[CACHESZ];
.endforeach
#endif
static const char tm_srcfile[] = __FILE__;
.if $(statcode)
#ifdef STAT
static const char tm_allocfreed[] = "%-15s: %6ld allocated, %6ld freed, %6ld cache hits.%s\n";
#endif
.endif
#ifndef FIRSTROOM
/* Default initial room in arrays. (uneducated guess). */
#define FIRSTROOM 2
#endif
#ifndef FATAL
#define FATAL(msg) tmfatal(tm_srcfile,__LINE__,msg)
#endif
#ifndef WORDBUFSIZE
#define WORDBUFSIZE 100
#endif
/* Possible error strings. */
static const char tm_outofmemory[] = "out of memory";
.if ${strlen $(need_del_list) $(need_ins_list)}
static const char tm_nilptr[] = "NIL pointer";
.endif
.if ${strlen $(need_fscan)}
static const char tm_badcons[] = "bad constructor for %s: '%s'";
.endif
.if ${strlen $(need_fscan_list)}
static const char tm_badeof[] = "unexpected end of file";
.endif
#ifndef FATALTAG
#define FATALTAG(tag) tmbadtag(tm_srcfile,__LINE__,tag)
#endif
/**************************************************
* array room routines *
**************************************************/
$(teststdc)
.foreach t $(need_room_list)
.if ${index $t $(want_room_list)}
.else
static void room_$t_list( $t_list, unsigned int );
.endif
.endforeach
#endif
.foreach t $(need_room_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_room_list)
.set stic_$t
.endforeach
.foreach t $(need_room_list)
/* Announce that you will need room for 'rm' elements in
$t_list 'l'.
*/
$(stic_$t)void room_$t_list( l, rm )
register $t_list l;
register unsigned int rm;
{
if( l->room>rm ){
return;
}
l->arr = ($t *) TMREALLOC( l->arr, rm * sizeof(*(l->arr)) );
if( l->arr == ($t *)0 ){
FATAL( tm_outofmemory );
}
l->room = rm;
}
.endforeach
/**************************************************
* Allocation routines *
**************************************************/
$(teststdc)
.foreach t $(need_new_list)
.if ${index $t $(want_new_list)}
.else
static $t_list new_$t_list( void );
.endif
.endforeach
.foreach t $(need_new)
.if ${index $t $(want_new)}
.else
.if ${len ${telmlist $t}}
.set tl
.foreach e ${telmlist $t}
.if ${eq single ${ttypeclass $t $e}}
.append tl ${ttypename $t $e}
.else
.append tl ${ttypename $t $e}_list
.endif
.endforeach
.if ${== ${len $(tl)} 0}
static $t new_$t( void );
.else
static $t new_$t( ${seplist ", " $(tl)} );
.endif
.else
.foreach c ${conslist $t}
.set tl
.foreach e ${celmlist $t $c}
.if ${eq single ${ctypeclass $t $c $e}}
.append tl ${ctypename $t $c $e}
.else
.append tl ${ctypename $t $c $e}_list
.endif
.endforeach
.if ${== ${len $(tl)} 0}
static $t new_$c( void );
.else
static $t new_$c( ${seplist ", " $(tl)} );
.endif
.endforeach
.endif
.endif
.endforeach
#endif
.foreach t $(need_new_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_new_list)
.set stic_$t
.endforeach
.foreach t $(need_new_list)
$(stic_$t)$t_list new_$t_list()
{
$t_list new;
#ifdef USECACHE
if( cacheix_$t_list > 0 ){
new = cache_$t_list[--cacheix_$t_list];
.if $(statcode)
#ifdef STAT
hitcnt_$t_list++;
#endif
.endif
}
else {
#endif
new = ($t_list) malloc( sizeof(*new) );
if( (char *)new == (char *)0 ){
FATAL( tm_outofmemory );
}
#ifdef USECACHE
}
#endif
new->sz = 0;
new->arr = ($t *) malloc( FIRSTROOM*sizeof( *(new->arr) ) );
new->room = FIRSTROOM;
if( (char *)new->arr == (char *)0 ){
FATAL( tm_outofmemory );
}
.if $(statcode)
#ifdef STAT
newcnt_$t_list++;
#endif
.endif
return new;
}
.endforeach
.foreach t $(need_new)
.set stic_$t "static "
.endforeach
.foreach t $(want_new)
.set stic_$t
.endforeach
.foreach t $(need_new)
.if ${strlen ${telmlist $t}}
.. new_<tuple>
$(stic_$t)$t new_$t( ${seplist ", " ${prefix "p_" ${telmlist $t}}} )
.foreach sname ${telmlist $t}
.if ${eq list ${ttypeclass $t $(sname)}}
${ttypename $t $(sname)}_list p_$(sname);
.else
${ttypename $t $(sname)} p_$(sname);
.endif
.endforeach
{
register $t new;
#ifdef USECACHE
if( cacheix_$t > 0 ){
new = cache_$t[--cacheix_$t];
.if $(statcode)
#ifdef STAT
hitcnt_$t++;
#endif
.endif
}
else {
#endif
new = ($t) malloc( sizeof(*new));
if( (char *)new == (char *)0 ){
FATAL( tm_outofmemory );
}
#ifdef USECACHE
}
#endif
.foreach sname ${telmlist $t}
new->$(sname) = p_$(sname);
.endforeach
.if $(statcode)
#ifdef STAT
newcnt_$t++;
#endif
.endif
return new;
}
.else
.. new_<cons>
.foreach c ${conslist $t}
$(stic_$t)$t new_$c( ${seplist ", " ${prefix "p_" ${celmlist $t $c}}} )
.foreach sname ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(sname)}}
${ctypename $t $c $(sname)}_list p_$(sname);
.else
${ctypename $t $c $(sname)} p_$(sname);
.endif
.endforeach
{
register $t new;
#ifdef USECACHE
if( cacheix_$t > 0 ){
new = cache_$t[--cacheix_$t];
.if $(statcode)
#ifdef STAT
hitcnt_$c++;
#endif
.endif
}
else {
#endif
new = ($t) malloc( sizeof(*new));
if( (char *)new == (char *)0 ){
FATAL( tm_outofmemory );
}
#ifdef USECACHE
}
#endif
new->tag = TAG$c;
.foreach sname ${celmlist $t $c}
new->$c.$(sname) = p_$(sname);
.endforeach
.if $(statcode)
#ifdef STAT
newcnt_$c++;
#endif
.endif
return new;
}
.endforeach
.endif
.endforeach
/**************************************************
* Freeing routines *
**************************************************/
$(teststdc)
.foreach t $(need_fre_list)
.if ${index $t $(want_fre_list)}
.else
static void fre_$t_list( $t_list );
.endif
.endforeach
.foreach t $(need_fre)
.if ${index $t $(want_fre)}
.else
static void fre_$t( $t );
.endif
.endforeach
#endif
.foreach t $(need_fre)
.set stic_$t "static "
.endforeach
.foreach t $(want_fre)
.set stic_$t
.endforeach
.foreach t $(need_fre)
.if ${strlen ${telmlist $t}}
.. fre_<tuple>
/* Free an element 'e' of type '$t'. */
$(stic_$t)void fre_$t( e )
$t e;
{
if( e == $tNIL ){
return;
}
.if $(statcode)
#ifdef STAT
frecnt_$t++;
#endif
.endif
#ifdef USECACHE
if( cacheix_$t<CACHESZ ){
cache_$t[cacheix_$t++] = e;
return;
}
#endif
TMFREE( e );
}
.else
.. fre_<cons>
/* Free an element 'e' of type '$t'. */
$(stic_$t)void fre_$t( e )
$t e;
{
if( e == $tNIL ){
return;
}
.if $(statcode)
#ifdef STAT
switch( e->tag ){
.foreach c ${conslist $t}
case TAG$c:
frecnt_$c++;
break;
.endforeach
default:
FATALTAG( (int) e->tag );
}
#endif
.endif
#ifdef USECACHE
if( cacheix_$t<CACHESZ ){
cache_$t[cacheix_$t++] = e;
return;
}
#endif
TMFREE( e );
}
.endif
.endforeach
.foreach t $(need_fre_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_fre_list)
.set stic_$t
.endforeach
.foreach t $(need_fre_list)
/* Free a list of $t elements 'l'. */
$(stic_$t)void fre_$t_list( l )
$t_list l;
{
if( l == $t_listNIL ){
return;
}
.if $(statcode)
#ifdef STAT
frecnt_$t_list++;
#endif
.endif
TMFREE( l->arr );
#ifdef USECACHE
if( cacheix_$t_list<CACHESZ ){
cache_$t_list[cacheix_$t_list++] = l;
return;
}
#endif
TMFREE( l );
}
.endforeach
/**************************************************
* Append routines *
**************************************************/
$(teststdc)
.foreach t $(need_app_list)
.if ${index $t $(want_app_list)}
.else
static void app_$t_list( $t_list, $t );
.endif
.endforeach
#endif
.foreach t $(need_app_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_app_list)
.set stic_$t
.endforeach
.foreach t $(need_app_list)
/* Append a $t element 'e' to list 'l'. */
$(stic_$t)void app_$t_list( l, e )
$t_list l;
$t e;
{
if( l->sz >= l->room ){
room_$t_list( l, (l->sz)+(l->sz) );
}
l->arr[l->sz] = e;
l->sz++;
}
.endforeach
/**************************************************
* Real append routines *
**************************************************/
$(teststdc)
.foreach t $(need_append_list)
.if ${index $t $(want_append_list)}
.else
static $t_list append_$t_list( $t_list, $t );
.endif
.endforeach
#endif
.foreach t $(need_append_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_append_list)
.set stic_$t
.endforeach
.foreach t $(need_append_list)
/* Append a $t element 'e' to list 'l', and return the new list. */
$(stic_$t)$t_list append_$t_list( l, e )
$t_list l;
$t e;
{
if( l->sz >= l->room ){
room_$t_list( l, (l->sz)+(l->sz) );
}
l->arr[l->sz] = e;
l->sz++;
return l;
}
.endforeach
/**************************************************
* ins_<type>_list routines *
**************************************************/
$(teststdc)
.foreach t $(need_ins_list)
.if ${index $t $(want_ins_list)}
.else
static void ins_$t_list( $t_list, unsigned int, $t );
.endif
.endforeach
#endif
.foreach t $(need_ins_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_ins_list)
.set stic_$t
.endforeach
.foreach t $(need_ins_list)
/* Insert a $t element 'e' to into list 'l' at position 'pos'. */
$(stic_$t)void ins_$t_list( l, pos, e )
register $t_list l;
unsigned int pos;
$t e;
{
register unsigned int ix;
if( l == $t_listNIL ){
FATAL( tm_nilptr );
}
if( l->sz >= l->room ){
room_$t_list( l, (l->sz)+(l->sz) );
}
if( pos>l->sz ) pos = l->sz;
for( ix=l->sz; ix>pos; ix-- ){
l->arr[ix] = l->arr[ix-1];
}
l->sz++;
l->arr[pos] = e;
}
.endforeach
/**************************************************
* Concatenate routines *
**************************************************/
$(teststdc)
.foreach t $(need_conc_list)
.if ${index $t $(want_conc_list)}
.else
static void conc_$t_list( $t_list, $t_list );
.endif
.endforeach
#endif
.foreach t $(need_conc_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_conc_list)
.set stic_$t
.endforeach
.foreach t $(need_conc_list)
/* Concatenate $t list 'lb' after $t list 'la'.
The list descriptor of list 'lb' is freed,
since its contents has been moved to 'la'.
*/
$(stic_$t)void conc_$t_list( la, lb )
$t_list la;
$t_list lb;
{
register unsigned int cnt;
register $t *sp;
register $t *dp;
room_$t_list( la, la->sz+lb->sz );
cnt = lb->sz;
sp = lb->arr;
dp = &la->arr[la->sz];
while( cnt!=0 ){
*dp++ = *sp++;
cnt--;
}
la->sz += lb->sz;
fre_$t_list( lb );
}
.endforeach
/**********************************************
* Real concatenate routines *
**********************************************/
$(teststdc)
.foreach t $(need_concat_list)
.if ${index $t $(want_concat_list)}
.else
static $t_list concat_$t_list( $t_list, $t_list );
.endif
.endforeach
#endif
.foreach t $(need_concat_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_concat_list)
.set stic_$t
.endforeach
.foreach t $(need_concat_list)
/* Concatenate $t list 'lb' after $t list 'la'.
The list descriptor of list 'lb' is freed,
since its contents has been moved to 'la'.
*/
$(stic_$t)$t_list concat_$t_list( la, lb )
$t_list la;
$t_list lb;
{
register unsigned int cnt;
register $t *sp;
register $t *dp;
room_$t_list( la, la->sz+lb->sz );
cnt = lb->sz;
sp = lb->arr;
dp = &la->arr[la->sz];
while( cnt!=0 ){
*dp++ = *sp++;
cnt--;
}
la->sz += lb->sz;
fre_$t_list( lb );
return la;
}
.endforeach
/**************************************************
* Recursive freeing routines *
**************************************************/
$(teststdc)
.foreach t $(need_rfre)
.if ${index $t $(want_rfre)}
.else
static void rfre_$t( $t );
.endif
.endforeach
.foreach t $(need_rfre_list)
.if ${index $t $(want_rfre_list)}
.else
static void rfre_$t_list( $t_list );
.endif
.endforeach
#endif
.. Forward declarations
.foreach t $(need_rfre)
.if ${index $t $(want_rfre)}
.else
static void rfre_$t();
.endif
.endforeach
.foreach t $(need_rfre_list)
.if ${index $t $(want_rfre_list)}
.else
static void rfre_$t_list();
.endif
.endforeach
.foreach t $(need_rfre)
.set stic_$t "static "
.endforeach
.foreach t $(want_rfre)
.set stic_$t
.endforeach
.foreach t $(need_rfre)
/* Recursively free an element 'e' of type '$t'
and all elements in it.
*/
.if ${strlen ${telmlist $t}}
$(stic_$t)void rfre_$t( e )
$t e;
{
if( e == $tNIL ){
return;
}
.foreach sname ${telmlist $t}
.if ${eq list ${ttypeclass $t $(sname)}}
rfre_${ttypename $t $(sname)}_list( e->$(sname) );
.else
rfre_${ttypename $t $(sname)}( e->$(sname) );
.endif
.endforeach
fre_$t( e );
}
.else
$(stic_$t)void rfre_$t( e )
$t e;
{
if( e == $tNIL ){
return;
}
switch( e->tag ){
.foreach c ${conslist $t}
case TAG$c:
.foreach sname ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(sname)}}
rfre_${ctypename $t $c $(sname)}_list( e->$c.$(sname) );
.else
rfre_${ctypename $t $c $(sname)}( e->$c.$(sname) );
.endif
.endforeach
break;
.endforeach
default:
FATALTAG( (int) e->tag );
}
fre_$t( e );
}
.endif
.endforeach
.foreach t $(need_rfre_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_rfre_list)
.set stic_$t
.endforeach
.foreach t $(need_rfre_list)
/* Recursively free a list of elements 'e' of type $t. */
$(stic_$t)void rfre_$t_list( e )
$t_list e;
{
unsigned int ix;
if( e == $t_listNIL ){
return;
}
for( ix=0; ix<e->sz; ix++ ) rfre_$t( e->arr[ix] );
fre_$t_list( e );
}
.endforeach
/**************************************************
* print_<type> and print_<type>_list routines *
**************************************************/
$(teststdc)
.foreach t $(need_print)
.if ${index $t $(want_print)}
.else
static void print_$t( $t );
.endif
.endforeach
.foreach t $(need_print_list)
.if ${index $t $(want_print_list)}
.else
static void print_$t_list( $t_list );
.endif
.endforeach
#endif
.. Forward declarations
.foreach t $(need_print)
.if ${index $t $(want_print)}
.else
static void print_$t();
.endif
.endforeach
.foreach t $(need_print_list)
.if ${index $t $(want_print_list)}
.else
static void print_$t_list();
.endif
.endforeach
.foreach t $(need_print)
.set stic_$t "static "
.endforeach
.foreach t $(want_print)
.set stic_$t
.endforeach
.foreach t $(need_print)
/* Print an element 't' of type '$t'
using print optimizer.
*/
$(stic_$t)void print_$t( t )
$t t;
{
.if ${strlen ${telmlist $t}}
if( t == $tNIL ){
printword( "@" );
return;
}
opentuple();
.foreach sname ${telmlist $t}
.if ${eq list ${ttypeclass $t $(sname)}}
print_${ttypename $t $(sname)}_list( t->$(sname) );
.else
print_${ttypename $t $(sname)}( t->$(sname) );
.endif
.endforeach
closetuple();
.else
if( t == $tNIL ){
printword( "@" );
return;
}
opencons();
switch( t->tag ){
.foreach c ${conslist $t}
case TAG$c:
printword( "$c" );
.foreach sname ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(sname)}}
print_${ctypename $t $c $(sname)}_list( t->$c.$(sname) );
.else
print_${ctypename $t $c $(sname)}( t->$c.$(sname) );
.endif
.endforeach
break;
.endforeach
default:
FATALTAG( (int) t->tag );
}
closecons();
.endif
}
.endforeach
.foreach t $(need_print_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_print_list)
.set stic_$t
.endforeach
.foreach t $(need_print_list)
/* Print a list of elements 'l' of type '$t'
using print optimizer.
*/
$(stic_$t)void print_$t_list( l )
$t_list l;
{
unsigned int ix;
if( l == $t_listNIL ){
printword( "@" );
return;
}
openlist();
for( ix=0; ix<l->sz; ix++ ) print_$t( l->arr[ix] );
closelist();
}
.endforeach
/***************************************************
* fprint_<type> and fprint_<type>_list routines *
***************************************************/
$(teststdc)
.foreach t $(need_fprint)
.if ${index $t $(want_print)}
.else
static void fprint_$t( FILE *, $t );
.endif
.endforeach
.foreach t $(need_fprint_list)
.if ${index $t $(want_fprint_list)}
.else
static void fprint_$t_list( FILE *, $t_list );
.endif
.endforeach
#endif
.. Forward declarations
.foreach t $(need_fprint)
.if ${index $t $(want_fprint)}
.else
static void fprint_$t();
.endif
.endforeach
.foreach t $(need_fprint_list)
.if ${index $t $(want_fprint_list)}
.else
static void fprint_$t_list();
.endif
.endforeach
.foreach t $(need_fprint)
.set stic_$t "static "
.endforeach
.foreach t $(want_fprint)
.set stic_$t
.endforeach
.foreach t $(need_fprint)
/* Print a $t 't' to file 'f'. */
$(stic_$t)void fprint_$t( f, t )
FILE *f;
$t t;
{
if( t == $tNIL ){
fputs( "@ ", f );
return;
}
putc( '(', f );
.if ${strlen ${telmlist $t}}
.set first 1
.foreach sname ${telmlist $t}
.if $(first)
.set first 0
.else
fputs( ",\n", f );
.endif
.if ${eq list ${ttypeclass $t $(sname)}}
fprint_${ttypename $t $(sname)}_list( f, t->$(sname) );
.else
fprint_${ttypename $t $(sname)}( f, t->$(sname) );
.endif
.endforeach
.else
switch( t->tag ){
.foreach c ${conslist $t}
case TAG$c:
fputs( "$c", f );
.foreach sname ${celmlist $t $c}
putc( ' ', f );
.if ${eq list ${ctypeclass $t $c $(sname)}}
fprint_${ctypename $t $c $(sname)}_list( f, t->$c.$(sname) );
.else
fprint_${ctypename $t $c $(sname)}( f, t->$c.$(sname) );
.endif
.endforeach
break;
.endforeach
default:
FATALTAG( (int) t->tag );
}
.endif
fputs( ")\n", f );
}
.endforeach
.foreach t $(need_fprint_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_fprint_list)
.set stic_$t
.endforeach
.foreach t $(need_fprint_list)
/* Print a $t list 'l' to file 'f'. */
$(stic_$t)void fprint_$t_list( f, l )
FILE *f;
$t_list l;
{
register unsigned int ix;
if( l == $t_listNIL ){
fputs( "@ ", f );
return;
}
putc( '[', f );
for( ix=0; ix<l->sz; ix++ ){
if( ix!=0 ){
fputc( ',', f );
}
fprint_$t( f, l->arr[ix] );
}
fputs( "]\n", f );
}
.endforeach
/**************************************************
* Duplication routines *
**************************************************/
$(teststdc)
.foreach t $(need_rdup)
.if ${index $t $(want_rdup)}
.else
static $t rdup_$t( $t );
.endif
.endforeach
.foreach t $(need_rdup_list)
.if ${index $t $(want_rdup_list)}
.else
static $t_list rdup_$t_list( $t_list );
.endif
.endforeach
#endif
.. Forward declarations
.foreach t $(need_rdup)
.if ${index $t $(want_rdup)}
.else
static $t rdup_$t();
.endif
.endforeach
.foreach t $(need_rdup_list)
.if ${index $t $(want_rdup_list)}
.else
static $t_list rdup_$t_list();
.endif
.endforeach
.foreach t $(need_rdup)
.set stic_$t "static "
.endforeach
.foreach t $(want_rdup)
.set stic_$t
.endforeach
.foreach t $(need_rdup)
/* Recursively duplicate a $t element 'e'. */
$(stic_$t)$t rdup_$t( e )
$t e;
{
.if ${strlen ${telmlist $t}}
.foreach e ${telmlist $t}
.if ${eq list ${ttypeclass $t $e}}
${ttypename $t $e}_list i_$e;
.else
${ttypename $t $e} i_$e;
.endif
.endforeach
if( e == $tNIL ){
return $tNIL;
}
.foreach e ${telmlist $t}
.if ${eq list ${ttypeclass $t $e}}
i_$e = rdup_${ttypename $t $e}_list( e->$e );
.else
i_$e = rdup_${ttypename $t $e}( e->$e );
.endif
.endforeach
return new_$t( ${seplist ", " ${prefix "i_" ${telmlist $t}}} );
.else
.. rdup_<cons>
if( e == $tNIL ){
return $tNIL;
}
switch( e->tag ){
.foreach c ${conslist $t}
case TAG$c:
{
.foreach e ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $e}}
${ctypename $t $c $e}_list i_$e;
.else
${ctypename $t $c $e} i_$e;
.endif
.endforeach
.foreach e ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $e}}
i_$e = rdup_${ctypename $t $c $e}_list( e->$c.$e );
.else
i_$e = rdup_${ctypename $t $c $e}( e->$c.$e );
.endif
.endforeach
return new_$c( ${seplist ", " ${prefix "i_" ${celmlist $t $c}}} );
}
.endforeach
default:
FATALTAG( (int) e->tag );
}
return $tNIL;
.endif
}
.endforeach
.foreach t $(need_rdup_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_rdup_list)
.set stic_$t
.endforeach
.foreach t $(need_rdup_list)
/* Recursively duplicate $t list 'e'. */
$(stic_$t)$t_list rdup_$t_list( e )
$t_list e;
{
unsigned int ix;
$t_list new;
if( e == $t_listNIL ){
return $t_listNIL;
}
new = new_$t_list();
room_$t_list( new, e->sz );
for( ix=0; ix<e->sz; ix++ ){
new = append_$t_list( new, rdup_$t( e->arr[ix] ) );
}
return new;
}
.endforeach
/**************************************************
* Comparison routines. *
**************************************************/
$(teststdc)
.foreach t $(need_cmp)
.if ${index $t $(want_cmp)}
.else
static int cmp_$t( $t, $t );
.endif
.endforeach
.foreach t $(need_cmp_list)
.if ${index $t $(want_cmp_list)}
.else
static int cmp_$t_list( $t_list, $t_list );
.endif
.endforeach
#endif
.. Forward declarations
.foreach t $(need_cmp)
.if ${index $t $(want_cmp)}
.else
static int cmp_$t();
.endif
.endforeach
.foreach t $(need_cmp_list)
.if ${index $t $(want_cmp_list)}
.else
static int cmp_$t_list();
.endif
.endforeach
.foreach t $(need_cmp)
.if ${index $t $(want_cmp)}
.set stat
.else
.set stat "static "
.endif
.if ${len ${telmlist $t}}
.. cmp_<tuple>
/* Compare two $t tuples. */
$(stat)int cmp_$t( a, b )
register $t a;
register $t b;
{
register int res;
res = 0;
.. A small optimization, but also takes care of NIL.
if( a == b ){
return 0;
}
if( a == $tNIL ){
return -1;
}
if( b == $tNIL ){
return 1;
}
.set first 1
.foreach ename ${telmlist $t}
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
.if $(first)
.set first 0
.else
if( res != 0 ){
return res;
}
.endif
res = cmp_$(tn)( a->$(ename), b->$(ename) );
.endforeach
return res;
}
.else
.. cmp_<cons>
/* Compare two $t constructors. */
$(stat)int cmp_$t( a, b )
$t a;
$t b;
{
register int res;
.. A small optimization, but also takes care of NIL.
if( a == b ){
return 0;
}
if( a == $tNIL ){
return -1;
}
if( b == $tNIL ){
return 1;
}
res = ( (int)a->tag - (int)b->tag);
if( res != 0 ){
return res;
}
switch( a->tag )
{
.foreach c ${conslist $t}
case TAG$c:
.set first 1
.foreach ename ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(ename)}}
.set tn ${ctypename $t $c $(ename)}_list
.else
.set tn ${ctypename $t $c $(ename)}
.endif
.if $(first)
.set first 0
.else
if( res != 0 ) break;
.endif
res = cmp_$(tn)( a->$c.$(ename), b->$c.$(ename) );
.endforeach
break;
.endforeach
default:
FATALTAG( (int) a->tag );
}
return res;
}
.endif
.endforeach
.foreach t $(need_cmp_list)
.if ${index $t $(want_cmp_list)}
.set stat
.else
.set stat "static "
.endif
/* Compare two $t lists. */
$(stat)int cmp_$t_list( a, b )
register $t_list a;
register $t_list b;
{
register int res;
register unsigned int ix;
.. A small optimization, but also takes care of NIL.
if( a == b ){
return 0;
}
if( a == $t_listNIL ){
return -1;
}
if( b == $t_listNIL ){
return 1;
}
ix = 0;
while( ix<a->sz || ix<b->sz ){
if( ix>=a->sz ){
return -1;
}
if( ix>=b->sz ){
return 1;
}
res = cmp_$t( a->arr[ix], b->arr[ix] );
if( res != 0 ){
return res;
}
ix++;
}
return 0;
}
.endforeach
/**************************************************
* Scan routines. *
**************************************************/
$(teststdc)
.foreach t $(need_fscan)
.if ${index $t $(want_fscan)}
.else
static int fscan_$t( FILE *, $t * );
.endif
.endforeach
.foreach t $(need_fscan_list)
.if ${index $t $(want_fscan_list)}
.else
static int fscan_$t_list( FILE *, $t_list * );
.endif
.endforeach
#endif
.. Forward declarations
.foreach t $(need_fscan)
.if ${index $t $(want_fscan)}
.else
static int fscan_$t();
.endif
.endforeach
.foreach t $(need_fscan_list)
.if ${index $t $(want_fscan_list)}
.else
static int fscan_$t_list();
.endif
.endforeach
.foreach t $(need_fscan)
.set stic_$t "static "
.endforeach
.foreach t $(want_fscan)
.set stic_$t
.endforeach
.foreach t $(need_fscan)
.if ${strlen ${telmlist $t}}
.. tuple type
/* Read a tuple of type $t
from file 'f' and allocate space for it.
Set the pointer 'p' to point to that structure.
*/
$(stic_$t)int fscan_$t( f, p )
FILE *f;
$t *p;
{
register short int err;
int c;
.foreach ename ${telmlist $t}
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
$(tn) l_$(ename);
.endforeach
.. Note that separate assignment is necessary, since there may
.. be weird <type>NIL definitions ..
.foreach ename ${telmlist $t}
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
l_$(ename) = $(tn)NIL;
.endforeach
*p = $tNIL;
if( fscanspace( f ) ){
return 1;
}
c = getc( f );
if( c == '@' ){
return 0;
}
ungetc( c, f );
err = tmfneedc( f, '(' );
if( err ){
return 1;
}
.set first 1
.foreach ename ${telmlist $t}
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
.if $(first)
.set first 0
.else
if( !err ) err = tmfneedc( f, ',' );
.endif
if( !err ) err = fscan_$(tn)( f, &l_$(ename) );
.endforeach
*p = new_$t( ${seplist ", " ${prefix " l_" ${telmlist $t}}} );
if( err ){
return 1;
}
return tmfneedc( f, ')' );
}
.else
/* Read an instance of a datastructure of type $t.
from file 'f' and allocate space for it. Set the pointer 'p' to
point to that structure.
*/
$(stic_$t)int fscan_$t( f, p )
FILE *f;
$t *p;
{
register int n;
int c;
char tm_word[WORDBUFSIZE];
register short int err = 0;
*p = $tNIL;
n = fscanopenbrac( f );
if( fscanspace( f ) ){
return 1;
}
c = getc( f );
if( c == '@' ){
return fscanclosebrac( f, n );
}
ungetc( c, f );
if( fscancons( f, tm_word ) ){
return 1;
}
.. First time in loop there should be no 'else' before the if,
.. in all other cases there should.
.set els
.foreach c ${conslist $t}
$(els)if( strcmp( tm_word, "$c" ) == 0 ){
.foreach ename ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(ename)}}
.set tn ${ctypename $t $c $(ename)}_list
.else
.set tn ${ctypename $t $c $(ename)}
.endif
$(tn) l_$(ename);
.endforeach
.foreach ename ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(ename)}}
.set tn ${ctypename $t $c $(ename)}_list
.else
.set tn ${ctypename $t $c $(ename)}
.endif
l_$(ename) = $(tn)NIL;
if( !err) err = fscan_$(tn)( f, &l_$(ename) );
.endforeach
*p = new_$c( ${seplist ", " ${prefix " l_" ${celmlist $t $c}}} );
}
.set els "else "
.endforeach
else {
(void) sprintf( tmerrmsg, tm_badcons, "$t", tm_word );
return 1;
}
if( err ){
return 1;
}
return fscanclosebrac( f, n );
}
.endif
.endforeach
.foreach t $(need_fscan_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_fscan_list)
.set stic_$t
.endforeach
.foreach t $(need_fscan_list)
/* Read an instance of a list of datastructure of type $t
from file 'f' and allocate space for it. Set the pointer 'p' to
point to that structure.
*/
$(stic_$t)int fscan_$t_list( f, p )
FILE *f;
$t_list *p;
{
register short int err = 0;
register int c;
int n;
$t new;
*p = $t_listNIL;
n = fscanopenbrac( f );
if( fscanspace( f ) ){
return 1;
}
c = getc( f );
if( c == '@' ){
return fscanclosebrac( f, n );
}
ungetc( c, f );
if( tmfneedc( f, '[' ) ){
return 1;
}
*p = new_$t_list();
if( fscanspace( f ) ){
return 1;
}
c = getc( f );
if( c == ']' ){
return 0;
}
if( c == EOF ){
(void) strcpy( tmerrmsg, tm_badeof );
return 1;
}
ungetc( c, f );
for(;;){
if( !err ) err = fscan_$t( f, &new );
*p = append_$t_list( *p, new );
if( err || fscanspace( f ) ){
return 1;
}
c = getc( f );
if( c == EOF ){
(void) strcpy( tmerrmsg, tm_badeof );
return 1;
}
if( c != ',' ){
ungetc( c, f );
break;
}
}
if( tmfneedc( f, ']' ) ){
return 1;
}
return fscanclosebrac( f, n );
}
.endforeach
/**************************************************
* del_<type>_list routines *
**************************************************/
$(teststdc)
.foreach t $(need_del_list)
.if ${index $t $(want_del_list)}
.else
static int del_$t_list( $t_list, unsigned int );
.endif
.endforeach
#endif
.foreach t $(need_del_list)
.set stic_$t "static "
.endforeach
.foreach t $(want_del_list)
.set stic_$t
.endforeach
.foreach t $(need_del_list)
/* Delete '$t' element at position 'pos' in list 'l'. */
$(stic_$t)void del_$t_list( l, pos )
register $t_list l;
unsigned int pos;
{
register unsigned int ix;
if( l == $t_listNIL ){
FATAL( tm_nilptr );
}
if( pos >= l->sz ){
return;
}
rfre_$t( l->arr[pos] );
l->sz--;
for( ix=pos; ix<l->sz; ix++ ){
l->arr[ix] = l->arr[ix+1];
}
}
.endforeach
/************************************************************
* Miscellaneous routines *
************************************************************/
.if ${index flush_$(basename) $(need_misc)}
/* Flush the allocation caches. */
void flush_$(basename)()
{
#ifdef USECACHE
register short int ix;
.foreach t ${uniq $(need_new_list) $(need_fre_list)}
for( ix=0; ix<cacheix_$t_list; ix++ ){
TMFREE( cache_$t_list[ix] );
}
cacheix_$t_list = 0;
.endforeach
.foreach t ${uniq $(need_new) $(need_fre)}
for( ix=0; ix<cacheix_$t; ix++ ){
TMFREE( cache_$t[ix] );
}
cacheix_$t = 0;
.endforeach
#endif
}
.endif
.if $(statcode)
/* Print allocation and freeing statistics to file 'f'. */
void stat_$(basename)( f )
FILE *f;
{
#ifdef STAT
.foreach t $(need_stat_list)
fprintf( f, tm_allocfreed, "[$t]", newcnt_$t_list, frecnt_$t_list, hitcnt_$t_list, ((newcnt_$t_list==frecnt_$t_list)? "": "<-") );
.endforeach
.foreach t $(need_stat)
.if ${strlen ${telmlist $t}}
fprintf(f,tm_allocfreed,"$t",newcnt_$t,frecnt_$t,hitcnt_$t,((newcnt_$t==frecnt_$t)? "": "<-") );
.else
.foreach c ${conslist $t}
fprintf(f,tm_allocfreed,"$c",newcnt_$c,frecnt_$c,hitcnt_$c,((newcnt_$c==frecnt_$c)? "": "<-") );
.endforeach
.endif
.endforeach
#else
f = f; /* to prevent 'f unused' from compiler and lint */
#endif
}
.endif
#else
/* WARNING: The code below is dummy code to fool lint. */
/* new_<cons> and new_<type> routines */
.foreach t $(want_new)
.if ${len ${telmlist $t}}
$t new_$t( ${seplist ", " ${prefix p_ ${telmlist $t}}} )
.foreach sname ${telmlist $t}
.if ${eq list ${ttypeclass $t $(sname)}}
${ttypename $t $(sname)}_list p_$(sname);
.else
${ttypename $t $(sname)} p_$(sname);
.endif
.endforeach
{
.foreach e ${telmlist $t}
p_$e = p_$e;
.endforeach
return ($t)0;
}
.else
.foreach c ${conslist $t}
$t new_$c( ${seplist ", " ${prefix "p_" ${celmlist $t $c}}} )
.foreach sname ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(sname)}}
${ctypename $t $c $(sname)}_list p_$(sname);
.else
${ctypename $t $c $(sname)} p_$(sname);
.endif
.endforeach
{
.foreach e ${celmlist $t $c}
p_$e = p_$e;
.endforeach
return ($t)0;
}
.endforeach
.endif
.endforeach
.foreach t $(want_new_list)
$t_list new_$t_list(){ return ($t_list)0; }
.endforeach
/* room_<type>_list() routines */
.foreach t $(want_room_list)
void room_$t_list( l, n )
$t_list l;
unsigned int n;
{
l = l;
n = n;
}
.endforeach
/* app_<type>_list() routines */
.foreach t $(want_app_list)
void app_$t_list( l, e )
$t_list l;
$t e;
{
l = l;
e = e;
}
.endforeach
/* append_<type>_list() routines */
.foreach t $(want_append_list)
$t_list append_$t_list( l, e )
$t_list l;
$t e;
{
e = e;
return l;
}
.endforeach
/* ins_<type>_list() routines */
.foreach t $(want_ins_list)
void ins_$t_list( l, ix, e )
$t_list l;
unsigned int ix;
$t e;
{
l=l;
ix=ix;
e=e;
}
.endforeach
/* del_<type>_list() routines */
.foreach t $(want_del_list)
void del_$t_list( l, ix )
$t_list l;
unsigned int ix;
{
l=l;
ix=ix;
}
.endforeach
/* conc_<type>_list() routines */
.foreach t $(want_conc_list)
void conc_$t_list( a, b )
$t_list a, b;
{
a=a;
b=b;
}
.endforeach
/* concat_<type>_list() routines */
.foreach t $(want_concat_list)
$t_list concat_$t_list( a, b ) $t_list a, b;
{
b=b;
return a;
}
.endforeach
/* fre_<type>_list() routines */
.foreach t $(want_fre_list)
void fre_$t_list( l ) $t_list l; { l=l; }
.endforeach
.foreach t $(want_fre)
void fre_$t( e ) $t e; { e=e; }
.endforeach
/* rfre_<type>_list() routines */
.foreach t $(want_rfre_list)
void rfre_$t_list( l ) $t_list l; { l=l; }
.endforeach
.foreach t $(want_rfre)
void rfre_$t( e ) $t e; { e=e; }
.endforeach
/* print_<type>() routines */
.foreach t $(want_print)
void print_$t( e ) $t e; { e=e; }
.endforeach
.foreach t $(want_print_list)
void print_$t_list( l ) $t_list l; { l=l; }
.endforeach
/* fprint_<type>() routines */
.foreach t $(want_fprint)
void fprint_$t( f, e ) FILE *f; $t e; { f=f; e=e; }
.endforeach
.foreach t $(want_fprint_list)
void fprint_$t_list( f, l ) FILE *f; $t_list l; { f=f; l=l; }
.endforeach
/* rdup_<type>() routines */
.foreach t $(want_rdup)
$t rdup_$t( e ) $t e; { return e; }
.endforeach
.foreach t $(want_rdup_list)
$t_list rdup_$t_list( l ) $t_list l; { return l; }
.endforeach
/* fscan_<type>() routines */
.foreach t $(want_fscan)
int fscan_$t( f, p ) FILE *f; $t *p; { p=p; return f==f; }
.endforeach
.foreach t $(want_fscan_list)
int fscan_$t_list( f, l ) FILE *f; $t_list *l; { l=l; return f==f; }
.endforeach
/* cmp_<type>() routines */
.foreach t $(want_cmp)
int cmp_$t( a, b ) $t a, b; { return a==b; }
.endforeach
.foreach t $(want_cmp_list)
int cmp_$t_list( a, b ) $t_list a,b; { return a==b; }
.endforeach
/* misc. functions */
.if ${index flush_$(basename) $(want_misc)}
void flush_$(basename)(){}
.endif
.if ${index stat_$(basename) $(want_misc)}
void stat_$(basename)( f ) FILE *f; { f=f; }
.endif
#endif
/* ---- end of ${tplfilename} ---- */